use serde::{Deserialize, Serialize};
//use serde_json::json;
//use serde_json::Result;

use std::env;
use std::fs::File;
use std::io::prelude::*;
//use std::path::Path;
//use std::path::PathBuf;

//use std::error::Error;

//use std::process;

pub fn my_exit_process(e: &dyn std::error::Error) {
    println!("{}", e);
    println!("{}", "程序终止执行后续步骤...");
    std::process::exit(1);
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Config {
    pub project_root: String,
    pub build_dir: String,
    pub bochs_command_args:String,
    pub nasm_command_target: String,
    pub nasm_extra_args: String,
    pub nasm_extra_args_list_file: bool,
    pub hard_sector_size: u32,
    pub original_hard_file: String,
    pub target_hard_file_name: String,
    pub target_hard_file_dir: String,
    pub bin_file_cfg: Vec<BinFileInfo>,
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct BinFileInfo {
    pub name: String,
    pub lsn: u32, //逻辑扇区号（Logical Sector Number，简称 LSN）
}

impl BinFileInfo {
    pub fn default() -> Self {
        Self {
            name: "a.obj".into(),
            lsn: 0,
        }
    }

    pub fn new(name: &str, lsn: u32) -> Self {
        Self {
            name: name.into(),
            lsn,
        }
    }
}

impl Config {
    pub fn init() -> Option<Config> {
        //获取当前工作目录
        let mut path_buf = env::current_dir().unwrap();
        path_buf.push("nasm.cfg");
        let path = path_buf.as_path();

        //找nasm.cfg
        //存在  -> 读内容
        if path.exists() {
            let res = Self::read();
            res
        } else {
            //不存在  ->默认生成一个文件
            let cfg: Config = Config::default();
            Self::write(&cfg);
            Some(cfg)
        } //end else
    } //end fn
} // end impl Default

impl Config {
    pub fn default() -> Self {
        let path_buf = env::current_dir().unwrap();

        let bin_file_info_1 = BinFileInfo::default();
        let mut vec: Vec<BinFileInfo> = vec![];
        vec.push(bin_file_info_1);

        Self {
            project_root: path_buf.to_str().unwrap().into(),
            build_dir: "build".into(),
            bochs_command_args: "-unlock -q -f \"D:\\Development\\Bochs\\Bochs-2.8\\bochsrc-a.txt\"".into(),
            nasm_command_target: "bin".into(),
            nasm_extra_args: " -Iinclude ".into(),
            nasm_extra_args_list_file:true,
            hard_sector_size: 512,

            original_hard_file: "D:\\Development\\Bochs\\Bochs-2.8\\b.img".into(),
            target_hard_file_name: "c.img".into(),
            target_hard_file_dir: "D:\\Development\\Bochs\\Bochs-2.8".into(),

            bin_file_cfg: vec,
        } //enf Self
    } //end fn
      //todo
    fn read() -> Option<Config> {
        let mut path = env::current_dir().unwrap();
        path.push("nasm.cfg");
        let path = path.as_path();
        let res = std::fs::read_to_string(path);

        match res {
            Ok(json_string) => {
                let json_res = serde_json::from_str::<Config>(&json_string);
                match json_res {
                    Ok(json_obj) => Some(json_obj),
                    Err(e) => {
                        println!("file: {}\nrow: {}", std::file!(), std::line!());
                        my_exit_process(&e);
                        None
                    }
                }
            }
            Err(e) => {
                println!("file: {}\nrow: {}", std::file!(), std::line!());
                my_exit_process(&e);
                None
            }
        }
    }

    pub fn write(cfg: &Config) {
        let json_str = serde_json::to_string_pretty(cfg).unwrap();

        let mut path_buf = env::current_dir().unwrap();
        path_buf.push("nasm.cfg");
        let path = path_buf.as_path();

        let mut f = File::create(path).unwrap();
        f.write_all(json_str.as_bytes()).unwrap();
    }
}

mod tests {
    //use super::Config;
    #[test]
    fn test_1() {
        Config::init();
    }
}
